package transport;

import network.NetworkLayer;
import utils.*;
import application.*;

public class TransportMessageHandler implements MessageHandler, Runnable {

	SynchQueue incoming = new SynchQueue();

	public void handleMessage(String msg) {
		incoming.add(msg);
	}

	void processMessage(String msg) {
		String[] splitMessage = msg.split(":");
		String destName = splitMessage[1];
		if (splitMessage[2].equalsIgnoreCase("ACK")) {
			if (TransportLayer.hashACKsend.containsKey(destName)) {
				TransportLayer.hashACKsend.get(destName).processAck(msg);
			}
		} else if (splitMessage[2].equalsIgnoreCase("HELLOACK")) {
			TransportLayer.handleIncomingACKTransaction(splitMessage[1]);
		} else if (splitMessage[2].equalsIgnoreCase("MESSAGE")) {
			if (TransportLayer.hashAckReceive.containsKey(splitMessage[1])) {
				if (TransportLayer.hashAckReceive.get(splitMessage[1]) == Integer
						.parseInt(splitMessage[3]) - 1) {
					NetworkLayer.send(splitMessage[1] + ":" + NetworkLayer.myID
							+ ":ACK:" + splitMessage[3]);
					TransportLayer.hashAckReceive.put(splitMessage[1], Integer
							.parseInt(splitMessage[3]));
					StringBuffer msgOut = new StringBuffer();
					msgOut.append(splitMessage[4]);
					for (int i = 5; i < splitMessage.length; i++) {
						msgOut.append(":").append(splitMessage[i]);
					}
					ApplicationLayer.receive(msgOut.toString());
				} else {
					NetworkLayer.send(splitMessage[1] + ":" + NetworkLayer.myID
							+ ":ACK:" + splitMessage[3]);
				}
			}
		} else if (splitMessage[2].equalsIgnoreCase("ENDACK")) {
			if (TransportLayer.hashAckReceive.containsKey(splitMessage[1])) {
				TransportLayer.hashAckReceive.remove(splitMessage[1]);
			}
		} else if (splitMessage[2].equalsIgnoreCase("MESSAGESW")) {
			if (!TransportLayer.hashSWReceive.containsKey(splitMessage[1])) {
				TransportLayer.hashSWReceive.put(splitMessage[1],
						new SWReceive(splitMessage[1], msg));
			} else {
				TransportLayer.hashSWReceive.get(splitMessage[1])
						.updateHashRCV(msg);
			}
		} else if (splitMessage[2].equalsIgnoreCase("HELLOSW")) {
			NetworkLayer.send(splitMessage[1] + ":" + NetworkLayer.myID + ":ACKSW:" + 0);
			if (!TransportLayer.hashSWReceive.containsKey(splitMessage[1])) {
				TransportLayer.hashSWReceive.put(splitMessage[1], 
					new SWReceive(splitMessage[1],
							Integer.parseInt(splitMessage[3])));
			}
		} else if (splitMessage[2].equalsIgnoreCase("ACKSW")) {
			if (TransportLayer.hashSWsend.containsKey(destName)) {
				TransportLayer.hashSWsend.get(destName).processAck(msg);
			}
		} else if (splitMessage[2].equalsIgnoreCase("ENDACKSW")) {
			if (TransportLayer.hashSWReceive.containsKey(splitMessage[1])) {
				TransportLayer.hashSWReceive.get(splitMessage[1]).discard();
			}
		}
	}

	public void run() {
		while (true) {
			String msg = incoming.get();
			String[] splitMessage = msg.split(":");
			if (splitMessage[2].equalsIgnoreCase("ACK")
					|| splitMessage[2].equalsIgnoreCase("NACK")
					|| splitMessage[2].equalsIgnoreCase("HELLOACK")
					|| splitMessage[2].equalsIgnoreCase("MESSAGE")
					|| splitMessage[2].equalsIgnoreCase("ENDACK")
					|| splitMessage[2].equalsIgnoreCase("HELLOSW")
					|| splitMessage[2].equalsIgnoreCase("ACKSW")
					|| splitMessage[2].equalsIgnoreCase("ENDACKSW")
					|| splitMessage[2].equalsIgnoreCase("MESSAGESW")) {
				processMessage(msg);
			} else {
				ApplicationLayer.receive(msg);
			}
		}
	}
}
